package cn.nkpro.elcube.cloud;

import cn.nkpro.elcube.cloud.idds.NkCloudIddsClient;
import cn.nkpro.elcube.exception.NkOperateNotAllowedException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;

import javax.validation.constraints.NotNull;
import java.util.List;

/**
 *
 * 抽象的云服务工具类
 *
 * 作用如下：
 *
 * 通过指定的dubbo group来获取对应的远程服务
 *
 * 特殊情况：
 * 如果目标组为空，使用本地服务
 * 如果当前组为空，使用本地服务
 * 如果目标同本地，使用本地服务
 * @param <T>
 */
public abstract class NkAbstractCloudService<T> implements BeanFactoryAware {

    /**
     * 当前服务所在的生产者组
     *
     */
    @Autowired
    protected NkCloudProperties cloudProperties;
    @Autowired(required = false)
    protected NkCloudIddsClient iddsClient;

    private BeanFactory beanFactory;

    protected abstract Class<T> targetType();

    protected T local(){
        return beanFactory.getBean(targetType().getSimpleName(),targetType());
    }

    protected T remote(String group){
        String beanName = String.format("%s@%s", targetType().getSimpleName(), group);
        T service = beanFactory.getBean(beanName, targetType());
        Assert.notNull(service,"Bean["+beanName+"]不存在");
        return service;
    }
    /**
     * 通过标识位查找对应的，查找对应的生产者
     */
    protected T switchTarget(String key){

        if(StringUtils.isNotBlank(cloudProperties.getId()) && StringUtils.contains(key,'@')){
            String group = StringUtils.substringAfter(key,"@");

            if(StringUtils.isNotBlank(group) && !StringUtils.equals(group,cloudProperties.getId())){
                String beanName = String.format("%s@%s", targetType().getSimpleName(), group);
                T service = beanFactory.getBean(beanName, targetType());
                Assert.notNull(service,"Bean["+beanName+"]不存在");

                return service;
            }
        }

        // 如果key没有服务标识，尝试通过idds获取对应的服务
        if(iddsClient!=null){
            List<NkCloudIddsClient.ID> ids = iddsClient.find(key);
            if(!ids.isEmpty() && StringUtils.isNotBlank(ids.get(0).getProducerId())){
                String beanName = String.format("%s@%s", targetType().getSimpleName(), ids.get(0).getProducerId());
                T service = beanFactory.getBean(beanName, targetType());
                Assert.notNull(service,"Bean["+beanName+"]不存在");
                return service;
            }
        }

        return beanFactory.getBean(targetType().getSimpleName(),targetType());
    }

    protected String clearSymbol(String key){
        return StringUtils.substringBefore(key,"@");
    }

    protected void throwErrorIfRemote(String key){
        if(StringUtils.contains(key,'@')){
            throw new NkOperateNotAllowedException("不支持远程服务调用");
        }
    }

    @SuppressWarnings("all")
    @Override
    public void setBeanFactory(@NotNull BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}
